package com.tangji.signaltower.websocket.session;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fqgj.common.utils.CollectionUtils;
import com.fqgj.common.utils.DateUtil;
import com.tangji.signaltower.enums.SubscriptionEnum;
import io.netty.channel.Channel;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.util.concurrent.GlobalEventExecutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * 连接池管理者
 * User: Amarendar
 * Date: 2020/6/4
 * Time: 下午2:35
 */
public class SessionFactory {

    private static final Logger logger = LoggerFactory.getLogger(SessionFactory.class);

    //产品和订阅的人之间的关系
    public static Map<String, UserGroup> userGroupHashMap = new HashMap<>();

    //为了实现单个用户的推送，比如结算客户端的弹窗
    public static Map<String, ServerSession> sessionIdAndSession = new HashMap<>();

    //保存了所有 灰名单用户的 token set  从数据库定时刷新替换更新  参考class WarningListInit
    public static Set<String> fakeUsersSet = new HashSet<>();

    //为了支持向所有用户发布同一样信息  比如 提示刷新
    public static ChannelGroup allChannels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);

    public static void updateSession(ServerSession oldSession, ServerSession newSession) {
        logger.info("==Session==, updateSession, oldSession:{}, newSession:{}", JSONObject.toJSONString(oldSession), JSONObject.toJSONString(newSession));
        removeOldSession(oldSession);
        addNewSession(newSession);
    }

    private static void addNewSession(ServerSession newSession) {
//        logger.info("==更新的订阅 添加新的订阅 ==,sessionId:{},products:{}", newSession.getSessionId(), JSON.toJSONString(newSession.getSubscription()));
//        List<String> subscription = newSession.getSubscription();
//        if (CollectionUtils.isEmpty(subscription)) {
//            return;
//        }
        logger.info("==Session==, updateSession, newSession:{}", JSONObject.toJSONString(newSession));

        allChannels.add(newSession.getChannel());
        sessionIdAndSession.put(newSession.getSessionId(), newSession);

        if (allChannels.size() > 100) {
            logger.error("==更新的订阅 添加新的订阅 注意 allChannels size 可能存在风险 ==,size:{}", allChannels.size());
        }

        if (sessionIdAndSession.size() > 500) {
            logger.error("==更新的订阅 添加新的订阅 注意 sessionIdAndSession size 可能存在风险 ==,size:{}", sessionIdAndSession.size());
        }

//        boolean isFakeUser = fakeUsersSet.contains(newSession.getSessionId());
//        subscription.forEach(product -> {
//            UserGroup userGroup = userGroupHashMap.get(product);
//            if(userGroup==null){
//                userGroup = new UserGroup();
//            }
//
//            if (isFakeUser) {
//                logger.info("==更新的订阅 添加新的订阅 fake==,sessionId:{},products:{}", newSession.getSessionId(), JSON.toJSONString(newSession.getSubscription()));
//                userGroup.addFakeUser(newSession);
//            } else {
//                logger.info("==更新的订阅 添加新的订阅 normal==,sessionId:{},products:{}", newSession.getSessionId(), JSON.toJSONString(newSession.getSubscription()));
//                userGroup.addNormalUser(newSession);
//            }
//
//            logger.info("== 更新的订阅 添加新的订阅 userGroup==,userGroup:{}", JSON.toJSONString(userGroup));
//            userGroupHashMap.put(product, userGroup);
//        });

//        logger.info("== 更新的订阅 添加新的订阅 userGroupHashMap==,userGroupHashMap:{}", JSON.toJSONString(userGroupHashMap));
    }

    private static void removeOldSession(ServerSession oldSession) {
        logger.info("==Session==, removeFromAllMap, oldSession:{}", JSONObject.toJSONString(oldSession));

        if (oldSession == null) {
            logger.info("== removeOldSession 更新的订阅 老的为空==,products:{}", JSONObject.toJSONString(oldSession));
            return;
        }

        logger.info("== removeOldSession 更新的订阅 ==,sessionId:{}", oldSession.getSessionId());
        sessionIdAndSession.remove(oldSession.getSessionId());
//        List<String> productList = oldSession.getSubscription();
//        if (CollectionUtils.isEmpty(productList)) {
//            return;
//        }
//
//        productList.forEach(product -> {
//            UserGroup userGroup = userGroupHashMap.get(product);
//            if (userGroup == null) {
//                return;
//            }
//
//            userGroup.removeSession(oldSession);
//            userGroupHashMap.put(product, userGroup);
//        });

        allChannels.remove(oldSession.getChannel());
    }


    /**
     * 获取用户连接数报告
     *
     * @return
     */
    public static List<String> getSessionDataReport() {
        List<String> report = new ArrayList<>();
        int cnt = 0;

        for (String product : userGroupHashMap.keySet()) {
            UserGroup userGroup = userGroupHashMap.get(product);
            if (userGroup == null) {
                continue;
            }

            cnt += userGroup.getFakeUserSessionIdMap().size() + userGroup.getNormalUserChannels().size();
        }


        //分组行情描述
        String date = DateUtil.getDate(new Date(), "yyyy-MM-dd HH:mm:ss");
        report.add("报告日期=" + date);
        report.add("tokenSession总计, " + "在线用户数:" + cnt);
        return report;
    }


    /**
     * 解除绑定关系
     *
     * @return
     */
    public static void removeFromAllMap(ServerSession s) {
        logger.info("==Session==, removeFromAllMap, serverSession:{}", JSONObject.toJSONString(s));
        removeOldSession(s);
        logger.info("用户下线移除所有行情订阅,user:{}", JSON.toJSONString(s.getWebUser()));
    }


    /**
     * 获取session对象
     */
    public static ServerSession getSession(String sessionId) {
        logger.info("==Session==, getSession, sessionId:{}", sessionId);
        final ServerSession serverSession = sessionIdAndSession.get(sessionId);
        logger.info("==Session==, getSession, sessionId:{}, serverSession:{}", sessionId, JSONObject.toJSONString(serverSession));
        return serverSession;
    }

    /**
     * 获取某个行情的订阅组
     *
     * @param product
     * @return
     */
    public static UserGroup getChannelGroup(String product) {
        //获取组
        UserGroup group = userGroupHashMap.get(product);
        if (null == group) {
            return null;
        }
        return group;
    }
}
